package com.example.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.Vo.*;
import com.example.common.constant.Const;
import com.example.entity.*;
import com.example.mapper.ObjectiveMapper;
import com.example.quartz.TJob;
import com.example.quartz.TJobService;
import com.example.service.*;
import com.example.util.TimeHWUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ptuDai
 * @since 2022-04-19
 */
@Service("objectiveService")
public class ObjectiveServiceImpl extends ServiceImpl<ObjectiveMapper, Objective> implements IObjectiveService {

    @Autowired
    IUserService userService;
    @Autowired
    ObjectiveMapper objectiveMapper;
    @Autowired
    IKeyResultsService keyResultsService;
    @Autowired
    IUserDepartmentService userDepartmentService;
    @Autowired
    IPositionService positionService;
    @Autowired
    TJobService tJobService;

    /**
     * 获取目标分页列表数据
     * @param pageObjectiveVO 分页
     * @param objectiveQuery 查询条件
     * @return
     */
    @Override
    public IPage<ObjectiveVO> selectPage(IPage<ObjectiveVO> pageObjectiveVO, ObjectiveQuery objectiveQuery) {
        final Integer currentUid = userService.getIdByUserName(SecurityContextHolder.getContext().getAuthentication().getName());
        if (Const.FLAG.equals(objectiveQuery.getCreateUid())) {
            objectiveQuery.setCreateUid(currentUid);
        }
        if (Const.FLAG.equals(objectiveQuery.getReviewUid())) {
            objectiveQuery.setReviewUid(currentUid);
        }
        return this.objectiveMapper.selectVOPage(pageObjectiveVO, objectiveQuery);
    }

    /**
     * 新增OKR
     * @param type 类型
     * @param editObjectiveVO 新增OKR数据
     */
    @Override
    public void add(Integer type, EditObjectiveVO editObjectiveVO) {
        final Integer currentUid = userService.getIdByUserName(SecurityContextHolder.getContext().getAuthentication().getName());
        Objective objective = new Objective();
        BeanUtils.copyProperties(editObjectiveVO, objective);
        objective.setType(type);
        if (ObjectUtil.isEmpty(objective.getParentId())){
            objective.setParentId(0);
        }
        objective.setStatus(Const.STATUS_WAIT);
        objective.setReview(Const.REVIEW_WAIT);
        objective.setCreateUid(currentUid);
        this.save(objective);
        List<KeyResults> keyResultsList = editObjectiveVO.getKeyResultsList();
        if (keyResultsList.size()>0){
            keyResultsList.forEach(keyResults -> keyResults.setObjectiveId(objective.getId()));
            keyResultsService.saveBatch(keyResultsList);
        }
        else {
            throw new RuntimeException("");
        }
    }

    /**
     * 获取上级目标
     *
     * @param type 类型
     * @return
     */
    @Override
    public List<Objective> parentObjectList(Integer type) {
        List<Objective> parentObjectList;
        switch (type) {
            // 部门目标上级为公司目标
            case Const.TYPE_DEPARTMENT:
                parentObjectList = this.list(new QueryWrapper<Objective>().select("id", "name")
                        .gt("status", Const.STATUS_WAIT)
                        .lt("status", Const.STATUS_COMPLETE)
                        .eq("type", Const.TYPE_COMPANY));
                break;
            // 个人目标上级为部门目标
            case Const.TYPE_USER:
                final Integer currentUid = userService.getIdByUserName(SecurityContextHolder.getContext().getAuthentication().getName());
                final UserDepartment ud = userDepartmentService.getOne(new QueryWrapper<UserDepartment>().eq("user_id", currentUid));
                parentObjectList = this.list(new QueryWrapper<Objective>().select("id", "name")
                        .gt("status", Const.STATUS_WAIT)
                        .lt("status", Const.STATUS_COMPLETE)
                        .eq("department_id", ud.getDepartmentId())
                        .eq("type", Const.TYPE_DEPARTMENT));
                break;
            // 公司目标无上级
            case Const.TYPE_COMPANY:
            default:
                parentObjectList = null;
        }
        return parentObjectList;
    }

    /**
     * 根据目标类型获取审核人
     *
     * @param type 类型
     * @return
     */
    @Override
    public List<Reviewer> reviewerList(Integer type) {
        List<Reviewer> reviewers;
        final Integer currentUid = userService.getIdByUserName(SecurityContextHolder.getContext().getAuthentication().getName());
        User user = userService.getOne(new QueryWrapper<User>().eq("id",currentUid));
        Position position = positionService.getById(user.getPositionId());
        reviewers = reviewer(position.getLevel(), new ArrayList<>());
        return reviewers;
    }

    /**
     * 根据用户职位等级获取其所有上级用户，若用户已经是最上级则获取本级用户
     *
     * @param level 用户id
     * @param reviewers 所有上级用户
     * @return
     */
    private List<Reviewer> reviewer(Integer level, List<Reviewer> reviewers) {
        Integer parentLevel = level - 1;
        if (parentLevel > 0) {
            List<Reviewer> collect;
            // 若用户的上级是主管，则只需要获取本部门的主管作为审核人
            if (parentLevel.equals(Const.POSITION_LEADER)){
                final Integer currentUid = userService.getIdByUserName(SecurityContextHolder.getContext().getAuthentication().getName());
                final UserDepartment ud = userDepartmentService.getOne(new QueryWrapper<UserDepartment>().eq("user_id", currentUid));
                collect = positionService.listReviewer(parentLevel,ud.getDepartmentId());
            }else {
                collect = positionService.listReviewer(parentLevel);
            }
            if (collect.size() > 0) {
                reviewers.addAll(collect);
            }
            reviewer(parentLevel, reviewers);
        } else {
            // 若用户没有上级，则判断reviewer中是否有数据了，没有则添加同等级人员到reviewer
            if (reviewers.size() == 0) {
                reviewers = positionService.listReviewer(level);
            }
        }
        return reviewers;
    }

    /**
     * 审核目标
     *
     * @param objective 目标
     */
    @Override
    public void review(Objective objective) {
        if (objective.getReview().equals(Const.REVIEW_PASS)) {
            // 若目标审核状态为通过，判断当前时间是否超过截止时间
            // 超过则设置目标状态为已超时，未超过则设置状态为进行中，并设置定时任务当目标到达截止时间将目标状态设为已超时
            if (objective.getEndTime().isBefore(LocalDateTime.now())){
                objective.setStatus(Const.STATUS_TIMEOUT);
            }else {
                objective.setStatus(Const.STATUS_RUNNING);
                // 设置定时任务时要判断当前任务是否已经添加过了，不排除之前这个目标已经审核过了设置了定时任务
                // 如果设置过了则先删除定时任务再重新设置定时任务
                try {
                    TJob tJob = tJobService.getOne(new QueryWrapper<TJob>().eq("job_name", objective.getId().toString()));
                    if (tJob != null) {
                        tJobService.removeJob(tJob);
                        tJobService.addJob(objective.getId().toString()
                                , TimeHWUtil.localDateTimeToDate(objective.getEndTime())
                                , "objectiveService.changeStatus"
                                , "(" + objective.getId() + "," + Const.STATUS_TIMEOUT + ")");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            this.update(objective,new UpdateWrapper<Objective>().set("reason",null).eq("id", objective.getId()));
        } else {
            // 若目标审核状态为未通过则设置目标状态为未开始，同时由于该目标之前可能已经通过审核，应该删除该目标的定时任务
            this.update(objective,
                    Wrappers.<Objective>lambdaUpdate().set(Objective::getCompleteTime, null)
                            .set(Objective::getStars,null)
                            .set(Objective::getStatus, Const.STATUS_WAIT)
                            .eq(Objective::getId, objective.getId()));
            TJob tJob = tJobService.getOne(new QueryWrapper<TJob>().eq("job_name", objective.getId().toString()));
            if (tJob != null) {
                tJobService.removeJob(tJob);
            }
        }
    }

    /**
     * 改变目标状态方法，用于定时任务反射执行
     *
     * @param id 目标id
     * @param status 目标状态
     */
    @Override
    public void changeStatus(Integer id, Integer status) {
        this.update(new UpdateWrapper<Objective>().set("status",status).eq("id", id).eq("status",Const.STATUS_RUNNING));
    }

    @Override
    public List<TreeObjectiveVO> tree() {
        return buildTreeObjective(objectiveMapper.tree());
    }

    private List<TreeObjectiveVO> buildTreeObjective(List<TreeObjectiveVO> list) {
        List<TreeObjectiveVO> tree = new ArrayList<>();
        for (TreeObjectiveVO objectiveVO : list) {
            // 先寻找各自的孩子
            for (TreeObjectiveVO e : list) {
                if (e.getParentId().equals(objectiveVO.getId())) {
                    objectiveVO.getChildren().add(e);
                }
            }
            // 提取出父节点
            if (objectiveVO.getParentId() == 0) {
                tree.add(objectiveVO);
            }
        }
        return tree;
    }
}
